package model.tests;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Collection;

import model.collisions.CollisionCategory;
import model.collisions.Collisionable;
import model.elements.Bomb;
import model.elements.Explotion;
import model.elements.attributes.Coordinate2D;
import model.elements.commands.ElementCommandFactory;
import model.elements.states.movement.MovingRight;
import model.exceptions.ElementOutOfBounds;
import model.exceptions.ModelExceptions;
import model.map.ElementsMap;

import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;

// TODO: Auto-generated Javadoc
/**
 * The Class BombTest.
 */
public class BombTest {

	/** The test map. */
	private static ElementsMap testMap = new ElementsMap(10, 10);
	
	/**
	 * Sets the up before class.
	 *
	 * @throws Exception the exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {		
		ElementCommandFactory.setup(testMap);
	}
	
	/**
	 * Tear down.
	 *
	 * @throws Exception the exception
	 */
	@After
	public void tearDown() throws Exception 
	{		
		testMap.clear();
	}
	
	/**
	 * Test set position.
	 *
	 * @throws ModelExceptions the model exceptions
	 */
	@Test
	public void testSetPosition() throws ModelExceptions {
		Bomb testBomb = new Bomb(new Coordinate2D(0,0));
		testBomb.setPosition(new Coordinate2D(1,1));
		assertTrue( testBomb.getPosition().equals( new Coordinate2D(1,1) ) );		
	}

	/**
	 * Test update.
	 *
	 * @throws ModelExceptions the model exceptions
	 */
	@Test
	public void testUpdate() throws ModelExceptions {
		
		Bomb testBomb = new Bomb(new Coordinate2D(0,0));
		
		try {
			testMap.addElement(testBomb);
		} catch (ElementOutOfBounds e) {
			e.printStackTrace();
		}
		
		testBomb.update();
		
		assertTrue( testBomb.getTTL().getValue() == 4 );		
		assertTrue( testBomb.getPosition().equals( new Coordinate2D(0,0) ) );
		
		while(testBomb.getTTL().getValue() > 0)
			testBomb.update();
		
		assertTrue( testBomb.isAlive() );
		
		testBomb.update();
		
		Collection<Collisionable> testList = testMap.getElementsIn( testBomb.getPosition() );		
		
		assertTrue( testList.size() == 5 );
		assertFalse( testBomb.isAlive() );
		
	}

	/**
	 * Test get position.
	 *
	 * @throws ModelExceptions the model exceptions
	 */
	@Test
	public void testGetPosition() throws ModelExceptions {
		Bomb testBomb = new Bomb(new Coordinate2D(0,0));
		assertTrue( testBomb.getPosition().equals( new Coordinate2D(0,0) ) );
	}

	/**
	 * Test reduce ttl.
	 *
	 * @throws ModelExceptions the model exceptions
	 */
	@Test
	public void testReduceTTL() throws ModelExceptions {
		Bomb testBomb = new Bomb(new Coordinate2D(0,0));
		testBomb.reduceTTL();
		assertTrue( testBomb.getTTL().getValue() == 4 );
	}

	/**
	 * Test get collision category.
	 *
	 * @throws ModelExceptions the model exceptions
	 */
	@Test
	public void testGetCollisionCategory() throws ModelExceptions {
		Bomb testBomb = new Bomb(new Coordinate2D(0,0));
		assertTrue( testBomb.getCollisionCategory() == CollisionCategory.C_T1_WALL );
	}

	/**
	 * Test take damage.
	 *
	 * @throws ModelExceptions the model exceptions
	 */
	@Test
	public void testTakeDamage() throws ModelExceptions {
		Bomb testBomb = new Bomb(new Coordinate2D(1,0));
		Explotion testExplotion = new Explotion( new Coordinate2D(0,0), new MovingRight() );
		testMap.addElement(testBomb);
		testMap.addElement(testExplotion);		
		testExplotion.update();
		assertTrue( testBomb.isAlive() ); //La bomba is dying
		testBomb.update();
		assertFalse( testBomb.isAlive() ); //La bomba is dead
		
	}

	/**
	 * Test is alive.
	 *
	 * @throws ModelExceptions the model exceptions
	 */
	@Test
	public void testIsAlive() throws ModelExceptions {
		Bomb testBomb = new Bomb(new Coordinate2D(0,0));
		assertTrue(testBomb.isAlive());
	}

	/**
	 * Test on death.
	 *
	 * @throws ModelExceptions the model exceptions
	 */
	@Test
	public void testOnDeath() throws ModelExceptions {
		Bomb testBomb = new Bomb(new Coordinate2D(1,0));
		testMap.addElement(testBomb);
		testBomb.kill();
		assertTrue( testBomb.isAlive() ); //La bomba is dying
		testBomb.update();
		assertFalse( testBomb.isAlive() ); //La bomba is dead
		assertTrue( testMap.getElementsIn( testBomb.getPosition() ).size() == 5 );
	}

}
